package negocios;

import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import negocios.excecoes.EntradaInvalidaException;
import negocios.excecoes.LocalizacaoException;
import negocios.excecoes.NaoEncontradoException;
import negocios.excecoes.OcultoException;
import negocios.excecoes.SessaoInexistenteException;

import org.w3c.dom.DOMException;

import util.Criptografia;
import bd.excecoes.XMLException;

/**
 * Fachada para testes do sistema I'm Here, usando EasyAccept. Implementa o
 * padrao Singleton.
 * 
 * @author Jonathan Brilhante
 * @author Jose Rafael
 * @author Nate Venancio
 * @author Renato Almeida
 * 
 * @link http://easyaccept.sourceforge.net/
 * @version 2.0
 */

public class FacadeTestes {
	private static final int NAO_PODE_VER = 1;
	private static final int PODE_VER = 2;
	private static String chatLogin1 = "";
	private static String chatLogin2 = "";

	private static FacadeTestes instance;
	private static FacadeNegocios sistema;

	private FacadeTestes() {
		sistema = FacadeNegocios.getInstance();
	}

	/**
	 * Retorna a instancia unica da fachada de testes.
	 * 
	 * @return a instancia unica.
	 */
	public static synchronized FacadeTestes getInstance() {
		if (instance == null) {
			instance = new FacadeTestes();
		}
		return instance;
	}

	public void criarUsuario(String login, String nome, String email,
			String senha, String telefone) throws EntradaInvalidaException,
			IOException, LocalizacaoException {
		sistema.criarUsuario(login, nome, email, senha, telefone);
	}

	public String getAtributoUsuario(String usuario, String atributo)
			throws NaoEncontradoException {
		Usuario us = sistema.buscaPorLogin(usuario);
		if (atributo.equalsIgnoreCase("nome")) {
			return us.getNome();
		} else if (atributo.equalsIgnoreCase("email")) {
			return us.getEmail();
		} else if (atributo.equalsIgnoreCase("username")) {
			return us.getLogin();
		} else if (atributo.equalsIgnoreCase("telefone")) {
			return us.getTelefone();
		}
		return "";
	}

	public String getUsuarioPorNome(String nome, int indice)
			throws EntradaInvalidaException {
		Collection<Usuario> ordenado = sistema.usuariosPorNome(nome);
		if (indice > ordenado.size()) {
			throw new EntradaInvalidaException("O usuario nao existe.");
		}
		Iterator<Usuario> it = ordenado.iterator();
		while (indice-- > 1) {
			it.next();
		}
		return it.next().getLogin();
	}

	public void atualizarUsuario(String usuario, String atributo, String valor)
			throws NaoEncontradoException, EntradaInvalidaException {
		if (atributo.equalsIgnoreCase("username")) {
			throw new EntradaInvalidaException(
					"Nao eh permitido alterar o username.");
		}
		Usuario us = sistema.buscaPorLogin(usuario);
		if (atributo.equalsIgnoreCase("nome")) {
			us.setNome(valor);
		} else if (atributo.equalsIgnoreCase("email")) {
			us.setEmail(valor);
		} else if (atributo.equalsIgnoreCase("senha")) {
			us.setSenha(valor);
		} else if (atributo.equalsIgnoreCase("telefone")) {
			us.setTelefone(valor);
		}
	}

	public void removerUsuario(String usuario) throws NaoEncontradoException,
			DOMException, EntradaInvalidaException, IOException, XMLException,
			LocalizacaoException {
		Usuario us = sistema.buscaPorLogin(usuario);
		String login = us.getLogin();
		String senha = Criptografia.decifra(us.getSenha());
		sistema.deletarUsuario(login, senha);
	}

	public void zerarSistema() throws XMLException, IOException {
		sistema.reset();
	}

	public void encerrarSistema() throws XMLException {
		sistema.sair();
	}

	public String login(String userName, String senha, String ip)
			throws NaoEncontradoException, LocalizacaoException, IOException {
		return sistema.logar(userName, senha, ip).getLogin();
	}

	public boolean estaConectado(String usuario) throws NaoEncontradoException {
		Usuario us;
		try {
			us = sistema.buscaPorLogin(usuario);
		} catch (NaoEncontradoException e) {
			return false;
		}
		return us.isLogado();
	}

	public void logout(String usuario) throws SessaoInexistenteException {
		sistema.deslogar(usuario);
	}

	public String cadastrarUsuario(String username, String nome, String email,
			String senha, String telefone, String ip)
			throws EntradaInvalidaException, IOException, LocalizacaoException,
			NaoEncontradoException {
		sistema.criarUsuario(username, nome, email, senha, telefone);
		return sistema.logar(username, senha, ip).getLogin();
	}

	public String getLocalizadores() {
		return "[GeoIP, Manual]";
	}

	public String getLocalizacao(String usuario) throws NaoEncontradoException,
			LocalizacaoException {
		return sistema.buscaPorLogin(usuario).localizacao().getGPS();
	}

	public String obterLocalizacao(String usuario)
			throws NaoEncontradoException, LocalizacaoException {
		return sistema.buscaPorLogin(usuario).localizacao().toString();
	}

	public void setLocalizacao(String usuario, String latitude, String Longitude)
			throws LocalizacaoException, NaoEncontradoException {
		double lat = Double.parseDouble(latitude);
		double longi = Double.parseDouble(Longitude);
		sistema.buscaPorLogin(usuario).setLocalizador(
				new LocalizadorManual(lat, longi));
	}

	public void initMensageiro(String sistema) {
		// no nosso sistema, nao eh necessario :)
	}

	public void setDiretorioGabaritos(String valor) {
		// no nosso sistema, o local dos gabaritos, eh fixo :)
	}

	public String enviarConvite(String de, String para)
			throws NaoEncontradoException, IOException {
		sistema.enviarConvite(de, para);
		return "Documento convite.txt enviado com sucesso.";
	}

	public String enviarEmail(String de, String para, String assunto, String msg)
			throws NaoEncontradoException, IOException {
		sistema.enviarEmail(de, para, assunto, msg);
		return "Email enviado com sucesso.";
	}

	public String enviarSMS(String de, String para, String msg)
			throws NaoEncontradoException, EntradaInvalidaException,
			IOException {
		sistema.enviarSMS(de, para, msg);
		return "SMS enviado com sucesso.";
	}

	public void confirmarCompartilhamento(String de, String com, String modo)
			throws NaoEncontradoException, EntradaInvalidaException {
		int m = Integer.parseInt(modo);
		switch (m) {
		case PODE_VER:
			sistema.confirmarCompartilhamento(de, com, false);
			break;
		case NAO_PODE_VER:
			sistema.confirmarCompartilhamento(de, com, true);
			break;
		}
	}

	public void recusarCompartilhamento(String de, String com) {
		// para recusar, basta nao confirmar :)
	}

	public String getAmigos(String usuario) throws NaoEncontradoException,
			SessaoInexistenteException {
		return sistema.getAmigos(usuario).toString();
	}

	public boolean possoVerLocalizacao(String usuario, String amigo)
			throws NaoEncontradoException {
		List<Relacionamento> amigos = null;
		try {
			amigos = sistema.getAmigos(amigo);
		} catch (SessaoInexistenteException e) {
			throw new NaoEncontradoException("Usuario desconhecido.");
		}
		for (Relacionamento a : amigos) {
			if (a.getAmigo().getLogin().equals(usuario)) {
				if (a.isOculto()) {
					return false;
				} else {
					return true;
				}
			}
		}
		throw new NaoEncontradoException("Usuario desconhecido.");
	}

	public void setCompartilhamento(String usuario, String amigo, String modo)
			throws NaoEncontradoException, SessaoInexistenteException {
		int m = Integer.parseInt(modo);
		List<Relacionamento> amigos = sistema.getAmigos(usuario);
		for (Relacionamento a : amigos) {
			if (a.getAmigo().getLogin().equals(amigo)) {
				switch (m) {
				case PODE_VER:
					a.compartilhar();
					break;
				case NAO_PODE_VER:
					a.ocultar();
					break;
				}
				return;
			}
		}
		throw new NaoEncontradoException("Usuario desconhecido.");
	}

	public void removerAmigo(String usuario, String amigo)
			throws NaoEncontradoException {
		Usuario us;
		try {
			us = sistema.buscaPorLogin(usuario);
		} catch (NaoEncontradoException e) {
			throw new NaoEncontradoException("Permissao negada.");
		}
		us.excluirAmigo(sistema.buscaPorLogin(amigo));
	}

	public String getLocalizacaoAmigo(String usuario, String amigo)
			throws OcultoException, LocalizacaoException,
			SessaoInexistenteException, NaoEncontradoException {
		List<Relacionamento> amigos;
		amigos = sistema.getAmigos(usuario);
		for (Relacionamento a : amigos) {
			if (a.getAmigo().getLogin().equals(amigo)) {
				try {
					return a.getLocalizacao().getGPS();
				} catch (OcultoException e) {
					return e.getMessage();
				}
			}
		}
		throw new NaoEncontradoException("Usuario desconhecido.");
	}

	public void setPortChat(int port) {
		// nao precisa fazer nada na atual versao :)
	}

	public void initChat(String usuario1, String usuario2)
			throws NaoEncontradoException {
		chatLogin1 = usuario1;
		chatLogin2 = usuario2;
		sistema.iniciarChat(usuario1, usuario2);
	}

	public void enviarMensagem(String destinatario, String mensagem)
			throws NaoEncontradoException {
		String remetente;
		if (destinatario.equals(chatLogin1)) {
			remetente = chatLogin2;
		} else {
			remetente = chatLogin1;
		}
		sistema.enviarMensagem(remetente, destinatario, mensagem);
	}

	public String receberMensagem(String remetente)
			throws NaoEncontradoException {
		String destinatario;
		if (remetente.equals(chatLogin1)) {
			destinatario = chatLogin2;
		} else {
			destinatario = chatLogin1;
		}
		return sistema.receberMensagem(remetente, destinatario);
	}

	public void encerrarChat(String usuario1, String usuario2)
			throws NaoEncontradoException, IOException {
		sistema.encerrarChat(usuario1, usuario2);
	}
}